/*
 * trypsyn_dsp.c
 * This file is part of trypsyn-dsp
 *
 * Copyright (C) 2012 - Luke William Westby
 *
 * trypsyn-dsp is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * trypsyn-dsp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with trypsyn-dsp. If not, see <http://www.gnu.org/licenses/>.
 */

#include "trypsyn_dsp.h"

/* -------------------------------------------------------------------------- *
 * extensions array, n_ext index
 * store file extension strings for use in search loop in open function. keep
 * the length of this array in n_ext
 * -------------------------------------------------------------------------- */

static const char extensions[2][5] = {
	".wav\0",
	".mp3\0"
};

static const int n_ext = 2;

/* -------------------------------------------------------------------------- *
 * trypsyn_error()
 *
 * takes an error code (defined in trypsyn_dsp.h) and parses it via a switch
 * block. copies the appropriate message into a string and then prints string
 * with line number and code file from which it was called. all functions in
 * the library return one of the error codes defined in trypsyn_dsp.h for use
 * with this function. typical usage is
 *
 *     int error = trypsyn_function(args);
 *     trypsyn_error(error, __LINE__, __FILE__);
 *
 * if the function was called in "file.c" on line 100, the output will be
 *
 *     $ trypsyn-dsp: file.c: 100: This is a message about the error.
 * -------------------------------------------------------------------------- */

void trypsyn_error(int error_code, int line, char *file) {

	char error_string[1028];

	switch(error_code) {
		case TRYPSYN_ERROR_NONE:
			return;
		case TRYPSYN_ERROR_MEM:
			strcpy(error_string, "Bad memory allocation");
			break;
		case TRYPSYN_ERROR_INVFILE:
			strcpy(error_string, "Unable to determine file type");
			break;
		case TRYPSYN_ERROR_NULLARG:
			strcpy(error_string, "Illegal NULL argument passed to function");
			break;
		case TRYPSYN_ERROR_NOFILE:
			strcpy(error_string, "Unable to open file. Check that file exists.");
			break;
	}
	
	fprintf(stderr, "trypsyn-dsp: %s: %d: %s\n", file, line, error_string);
	exit(error_code);
}			

/* -------------------------------------------------------------------------- *
 * trypsyn_open()
 *
 * attempt to open a file located at the directory named in file_name cstring.
 * store the file type in file_type (no way, bro!) and if the file was
 * successfully openned, point to it with fp. it should now be clear that we
 * are using stdio for file manip rather than fcntl so the Mac owners can get
 * in on the fun. at completion trypsyn_open() will be able to parse filename
 * extensions and also open the file and read just enough to determine if the
 * file is a supported audio format or not. typical usage:
 *
 *     char *file_name = argv[1]; // or something else, whatever you want
 *     int file_type; // don't have to initialize
 *     FILE *fp = NULL; // just in case ;)
 *     int error;
 *     error = trypsyn_open(file_name, &file_type, fp);
 *
 * if all goes according to plan, fp will point to file context for stdio and
 * file_type will be of the corresponding value listed in the docs
 * -------------------------------------------------------------------------- */

int trypsyn_open(char *file_name, int *file_type, FILE **fp) {

	int i;
	
	trypsyn_uint8_t prefix[4];
	
	if(file_type == NULL || file_name == NULL)
		return TRYPSYN_ERROR_NULLARG;
	
	if(*fp != NULL) fclose(*fp);
	
	// check filename for extension
	*file_type = -1;
	for(i = 0; i < n_ext; i++) {
		if(strstr(file_name, extensions[i]) != NULL) *file_type = i;
	}
	
	*fp = fopen(file_name, "rb");
	if(*fp == NULL) return TRYPSYN_ERROR_NOFILE;
	
	// no file extension found
	// TODO try and guess the file from the first four bytes
	// for now, just return an error
	if(*file_type == -1) {
		return TRYPSYN_ERROR_INVFILE;
	}
	
	return TRYPSYN_ERROR_NONE;
}

/* -------------------------------------------------------------------------- *
 * trypsyn_close()
 *
 * just a rapper for fclose, to maintain logical symmetry or whatever. i think
 * it looks nicer so its there.
 * -------------------------------------------------------------------------- */

int trypsyn_close(FILE *fp) {
	
	fclose(fp);
}
